package cn.lbd.auth.service.impl;

import cn.lbd.auth.dao.*;
import cn.lbd.auth.entity.*;
import cn.lbd.auth.model.OperatorRole ;
import cn.lbd.auth.model.Resource ;
import cn.lbd.auth.model.RoleAuth ;
import cn.lbd.auth.service.AdminService;
import cn.lbd.auth.utils.ResourceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;

@Service
public class AdminServiceImpl implements AdminService {

    private static final String TIME_OUT = "timeOut";
    private static final String RE_COUNT = "reCount";

    //	private Map<String, Collection<ConfigAttribute>> resourceRoleMap = new ConcurrentHashMap<String, Collection<ConfigAttribute>>();

    @Autowired(required = false)
    private UserDao userDao;

    @Autowired(required = false)
    private UserRoleDao userRoleDao;

    @Autowired(required = false)
    private ResRoleDao resRoleDao;

    @Autowired(required = false)
    private OperatorRoleDao operatorRoleDao;

    @Autowired(required = false)
    private RoleAuthDao roleAuthDao;

    @Autowired(required = false)
    private ResDao resDao;


    /**
     * 根据工号获取操作员信息
     *
     * @param operatorId
     */
    @Override
    public User getOperatorById(Integer operatorId) {
        return userDao.selectOperatorById(operatorId);
    }


    /**
     * 获取操作员归属角色
     *
     * @param operatorId
     * @return
     */
    @Override
    public List<Role> getRoleByOperatorId(Integer operatorId) {
        return userRoleDao.selectRoleByOperatorId(operatorId);
    }



    @Override
    public List<Resource> getAllRoleResourceRela() {
        return null;
    }

    /**
     * 查找资源路径及其对应的角色
     *
     * @return Map<String, Collection < String>>
     */
    @Override
    public List<ResourceRole> getRoleAliasByResourceUrl() {
        return resRoleDao.selectRoleAliasByResourceUrl();
    }

    @Override
    public int getOrgIdByOperatorId(int operatorId) {
        String orgNameFull = userDao.selectOrgNameFullByOperatorId(operatorId);
        return userDao.selectByFullName(orgNameFull);
    }

    @Override
    public String loginVerify(String password, String id, int loginType) {
        User user = null;
        if (loginType == 0) {
            //账户登录
            user = userDao.selectOperatorById(Integer.parseInt(id));
        } else if (loginType == 1) {
            //notes登录
            user = userDao.selectOperatorByLoginName(id);
        }
        String errMsg = "";
        if (user == null) {
            if (loginType == 0) {
                errMsg = "账户不存在";
            } else if (loginType == 1) {
                errMsg = "notes用户认证失败";
            }
            return errMsg;
        }

        return getErrMsg(user, loginType);
    }

    private String getErrMsg(User user, int loginType) {
        String lastErrTimeStr = user.getLastErrTime();
        long mini = isReset(lastErrTimeStr);
        String errMsg = "";
        int timeOut = ResourceUtil.getValue(TIME_OUT) == null ? 30 : Integer.parseInt(ResourceUtil.getValue(TIME_OUT));
        int reCount = ResourceUtil.getValue(RE_COUNT) == null ? 5 : Integer.parseInt(ResourceUtil.getValue(RE_COUNT));
        if (mini > timeOut) {
            user.setErrCount(1);
            userDao.resetErrCount(user);
            if (loginType == 0) {
                errMsg = "密码错误，还可以重试" + (reCount - 1) + "次";
            } else if (loginType == 1) {
                errMsg = "notes用户认证失败，还可以重试" + (reCount - 1) + "次";
            }
            return errMsg;
        }
        if (user.getErrCount() < reCount) {
            userDao.updateErrCount(user.getOperatorId());
        }
        if (user.getErrCount() + 1 < reCount) {
            if (loginType == 0) {
                errMsg = "密码错误，还可以重试" + (reCount - user.getErrCount() - 1) + "次";
            } else if (loginType == 1) {
                errMsg = "notes用户认证失败，还可以重试" + (reCount - user.getErrCount() - 1) + "次";
            }
            return errMsg;
        }
        if (loginType == 0) {
            errMsg = "密码错误，已重试5次， 请" + (timeOut - mini) + "分钟后再试！ ";
        } else if (loginType == 1) {
            errMsg = "notes用户认证失败，已重试5次， 请" + (timeOut - mini) + "分钟后再试！";
        }
        return errMsg;
    }

    private long isReset(String lastErrTimeStr) {
        long mini = 0;
        if (lastErrTimeStr != null && lastErrTimeStr.length() > 0) {
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime lastErrTime = LocalDateTime.parse(lastErrTimeStr, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            mini = ChronoUnit.MINUTES.between(lastErrTime, now);
        }
        return mini;
    }

    @Override
    public void resetErrCount(String id, int loginType) {
        User user = null;
        if (loginType == 0) {
            //账户登录
            user = userDao.selectOperatorById(Integer.parseInt(id));
        } else if (loginType == 1) {
            //notes登录
            user = userDao.selectOperatorByLoginName(id);
        }
        if (user == null) {
            return;
        }
        user.setErrCount(0);
        userDao.resetErrCount(user);
    }

    @Override
    public String checkUserLock(String password, String id, int loginType) {
        User user = null;
        if (loginType == 0) {
            //账户登录
            user = userDao.selectOperatorById(Integer.parseInt(id));
        } else if (loginType == 1) {
            //notes登录
            user = userDao.selectOperatorByLoginName(id);
        }
        if (user == null) {
            return null;
        }
        String lastErrTimeStr = user.getLastErrTime();
        long mini = isReset(lastErrTimeStr);
        int timeOut = 30;
        int reCount = 5;
        if (user.getErrCount() >= reCount && mini <= timeOut) {
            return "账户已被锁，请" + (timeOut - mini) + "分钟后再试！";
        }
        return null;
    }

    @Override
    public User selectOperatorByLoginName(String name) {
        return userDao.selectOperatorByLoginName(name);
    }


    /**
     * 通过账号查出角色
     */
    @Override
    public List<OperatorRole> getOperatorRoleByOperId(Integer operatorId) {
        return operatorRoleDao.selectOperatorRoleByOperId(operatorId);
    }

    /**
     * 根据角色查出权限
     *
     * @param roleId
     * @return
     */
    @Override
    public List<RoleAuth> getAuthByRoleId(Integer roleId) {
        return roleAuthDao.selectAuthByRoleId(roleId);
    }

    /**
     * 根据资源id获取资源
     *
     * @param resId
     * @return
     */
    @Override
    public Resource getResourceByResId(Integer resId) {
        return resDao.getResourceByResId(resId);
    }
}
